#include <grpcpp/grpcpp.h>
#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include "./generated/graph_service.grpc.pb.h"
#include <nlohmann/json.hpp>

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using namespace graph;
using json = nlohmann::json;

class GraphDbClient {
public:
    GraphDbClient(const std::string& server_address) {
        auto channel = grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials());
        stub_ = GraphService::NewStub(channel);
    }
    
    // 打印图结构的辅助函数
    void PrintGraphStructure(const GenericSubgraph& subgraph) {
        std::cout << "\n=== 图结构信息 ===" << std::endl;
        std::cout << "节点数量: " << subgraph.nodes_size() << std::endl;
        std::cout << "边数量: " << subgraph.relationships_size() << std::endl;
        
        // 打印所有节点
        std::cout << "\n--- 节点列表 ---" << std::endl;
        for (int i = 0; i < subgraph.nodes_size(); ++i) {
            const auto& node = subgraph.nodes(i);
            std::cout << "  [" << i << "] ID: " << node.id() 
                      << ", 标签: " << node.label() 
                      << ", 属性: " << node.properties_json() << std::endl;
        }
        
        // 打印所有边
        std::cout << "\n--- 边列表 ---" << std::endl;
        for (int i = 0; i < subgraph.relationships_size(); ++i) {
            const auto& rel = subgraph.relationships(i);
            std::cout << "  [" << i << "] " 
                      << rel.start_node_id() << "(" << rel.start_node_label() << ")"
                      << " --[" << rel.type() << "]--> "
                      << rel.end_node_id() << "(" << rel.end_node_label() << ")"
                      << ", 属性: " << rel.properties_json() << std::endl;
        }
        
        // 构建可视化图结构
        std::cout << "\n--- 图结构可视化 ---" << std::endl;
        for (int i = 0; i < subgraph.relationships_size(); ++i) {
            const auto& rel = subgraph.relationships(i);
            std::cout << "  ┌─ " << rel.start_node_label() << "(" << rel.start_node_id() << ")" << std::endl;
            std::cout << "  │" << std::endl;
            std::cout << "  ├─ [" << rel.type() << "]" << std::endl;
            std::cout << "  │" << std::endl;
            std::cout << "  └─ " << rel.end_node_label() << "(" << rel.end_node_id() << ")" << std::endl;
            std::cout << std::endl;
        }
    }
    
    // 打印 Cypher 查询结果
    void PrintCypherResult(const CypherResult& result) {
        std::cout << "\n=== Cypher 查询结果 ===" << std::endl;
        std::cout << "总行数: " << result.total_count() << std::endl;
        std::cout << "是否有记录: " << (result.has_records() ? "是" : "否") << std::endl;
        
        if (result.rows_size() > 0) {
            std::cout << "\n--- 查询结果详情 ---" << std::endl;
            for (int row_idx = 0; row_idx < result.rows_size(); ++row_idx) {
                const auto& row = result.rows(row_idx);
                
                std::cout << "行 " << row_idx << ":" << std::endl;
                
                // 打印字段名和值
                for (int col_idx = 0; col_idx < row.field_names_size(); ++col_idx) {
                    std::string field_name = row.field_names(col_idx);
                    std::string field_value = row.field_values(col_idx);
                    std::string field_type = row.field_types(col_idx);
                    
                    std::cout << "  " << field_name << " (" << field_type << "): " 
                              << field_value << std::endl;
                }
                std::cout << std::endl;
            }
        }
    }
    
    // 测试根据List ID获取子图
    void TestGetSubgraphByListId(int32_t list_id) {
        // 创建请求
        GetSubgraphByListIdRequest request;
        request.set_list_id(list_id);
        
        // 创建响应
        GetSubgraphByListIdResponse response;
        
        // 创建客户端上下文
        ClientContext context;
        
        // 调用RPC方法
        std::cout << "Calling GetSubgraphByListId with list_id: " << list_id << std::endl;
        Status status = stub_->GetSubgraphByListId(&context, request, &response);
        
        if (status.ok()) {
            std::cout << "GetSubgraphByListId SUCCESS" << std::endl;
            
            // 检查响应状态
            if (response.success()) {
                std::cout << "业务处理成功" << std::endl;
                
                // 打印图结构
                if (response.has_subgraph()) {
                    PrintGraphStructure(response.subgraph());
                } else {
                    std::cout << "返回的子图为空" << std::endl;
                }
            } else {
                std::cout << "业务处理失败: " << response.error_message() << std::endl;
            }
            
        } else {
            std::cout << "GetSubgraphByListId FAILED" << std::endl;
            std::cout << "Error code: " << status.error_code() << std::endl;
            std::cout << "Error message: " << status.error_message() << std::endl;
        }
        std::cout << "----------------------------------------" << std::endl;
    }
    
    // 测试根据User ID获取子图
    void TestGetSubgraphByUserId(int32_t user_id) {
        // 创建请求
        GetSubgraphByUserIdRequest request;
        request.set_user_id(user_id);
        
        // 创建响应
        GetSubgraphByUserIdResponse response;
        
        // 创建客户端上下文
        ClientContext context;
        
        // 调用RPC方法
        std::cout << "Calling GetSubgraphByUserId with user_id: " << user_id << std::endl;
        Status status = stub_->GetSubgraphByUserId(&context, request, &response);
        
        if (status.ok()) {
            std::cout << "GetSubgraphByUserId SUCCESS" << std::endl;
            
            // 检查响应状态
            if (response.success()) {
                std::cout << "业务处理成功" << std::endl;
                
                // 打印图结构
                if (response.has_subgraph()) {
                    PrintGraphStructure(response.subgraph());
                } else {
                    std::cout << "返回的子图为空" << std::endl;
                }
            } else {
                std::cout << "业务处理失败: " << response.error_message() << std::endl;
            }
            
        } else {
            std::cout << "GetSubgraphByUserId FAILED" << std::endl;
            std::cout << "Error code: " << status.error_code() << std::endl;
            std::cout << "Error message: " << status.error_message() << std::endl;
        }
        std::cout << "----------------------------------------" << std::endl;
    }
    
    // 测试 Neo4jRun 接口
    void TestNeo4jRun(const std::string& cypher_query, const json& parameters = json::object()) {
        // 创建请求
        Neo4jRunRequest request;
        request.set_cypher(cypher_query);
        
        // 设置参数 - 现在使用 Neo4jMap
        auto* params = request.mutable_parameters();
        for (auto& [key, value] : parameters.items()) {
            // 正确的方式：使用 protobuf map 的访问方法
            graph::Neo4jValue* param_value = &(*params->mutable_fields())[key];
            
            if (value.is_string()) {
                param_value->set_string_value(value.get<std::string>());
            } else if (value.is_number_integer()) {
                param_value->set_int_value(value.get<int64_t>());
            } else if (value.is_number_float()) {
                param_value->set_float_value(value.get<double>());
            } else if (value.is_boolean()) {
                param_value->set_bool_value(value.get<bool>());
            } else if (value.is_null()) {
                param_value->set_null_value(0);  // null_value 是占位符
            } else if (value.is_array()) {
                // 处理数组类型
                auto* list_value = param_value->mutable_list_value();
                for (const auto& item : value) {
                    graph::Neo4jValue* list_item = list_value->add_values();
                    if (item.is_string()) {
                        list_item->set_string_value(item.get<std::string>());
                    } else if (item.is_number_integer()) {
                        list_item->set_int_value(item.get<int64_t>());
                    } else if (item.is_number_float()) {
                        list_item->set_float_value(item.get<double>());
                    } else if (item.is_boolean()) {
                        list_item->set_bool_value(item.get<bool>());
                    } else {
                        list_item->set_string_value(item.dump());
                    }
                }
            } else if (value.is_object()) {
                // 处理对象类型
                auto* map_value = param_value->mutable_map_value();
                for (auto& [map_key, map_value_item] : value.items()) {
                    graph::Neo4jValue* map_item = &(*map_value->mutable_fields())[map_key];
                    if (map_value_item.is_string()) {
                        map_item->set_string_value(map_value_item.get<std::string>());
                    } else if (map_value_item.is_number_integer()) {
                        map_item->set_int_value(map_value_item.get<int64_t>());
                    } else if (map_value_item.is_number_float()) {
                        map_item->set_float_value(map_value_item.get<double>());
                    } else if (map_value_item.is_boolean()) {
                        map_item->set_bool_value(map_value_item.get<bool>());
                    } else {
                        map_item->set_string_value(map_value_item.dump());
                    }
                }
            } else {
                param_value->set_string_value(value.dump());
            }
        }
        
        // 创建响应
        Neo4jRunResponse response;
        
        // 创建客户端上下文
        ClientContext context;
        
        // 调用RPC方法
        std::cout << "Calling Neo4jRun with query: " << cypher_query << std::endl;
        if (!parameters.empty()) {
            std::cout << "Parameters: " << parameters.dump() << std::endl;
        }
        
        Status status = stub_->Neo4jRun(&context, request, &response);
        
        if (status.ok()) {
            std::cout << "Neo4jRun SUCCESS" << std::endl;
            
            // 检查响应状态
            if (response.success()) {
                std::cout << "业务处理成功" << std::endl;
                
                // 打印查询结果
                if (response.has_result()) {
                    PrintCypherResult(response.result());
                } else {
                    std::cout << "返回的查询结果为空" << std::endl;
                }
            } else {
                std::cout << "业务处理失败: " << response.error_message() << std::endl;
            }
            
        } else {
            std::cout << "Neo4jRun FAILED" << std::endl;
            std::cout << "Error code: " << status.error_code() << std::endl;
            std::cout << "Error message: " << status.error_message() << std::endl;
        }
        std::cout << "----------------------------------------" << std::endl;
    }
    
private:
    std::unique_ptr<GraphService::Stub> stub_;
};

// 主函数
int main() {
    try {
        // 创建客户端（假设服务运行在本地8004端口）
        GraphDbClient client("localhost:8004");
        
        std::cout << "Starting gRPC client tests..." << std::endl;
        
        // 测试 GetSubgraphByListId 接口
        client.TestGetSubgraphByListId(201);
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 短暂延迟
        
        // 测试 GetSubgraphByUserId 接口
        client.TestGetSubgraphByUserId(101);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        
        // 测试 Neo4jRun 接口 - 查询用户
        // "MATCH (parent_node {id: $id})-[r]->(son_node) RETURN parent_node, r, son_node",
        client.TestNeo4jRun(
            "MATCH (u:User {id: $id}) RETURN u.id, u.username, u.email",
            {{"id", 101}}
        );
        
        std::cout << "All tests completed!" << std::endl;
        
    } catch (const std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}